#This file is part of tryton-rrhh project. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
from trytond.model import ModelView, ModelSQL, fields
from trytond.pool import Pool, PoolMeta
from datetime import datetime
from dateutil.relativedelta import relativedelta
from trytond.transaction import Transaction
from trytond.pyson import Bool, Eval, If

__all__ = ['Employee', 'Department', 'Position', 'InstructionLevel', 'Dependent', 'DependentRelation',
            'DocumentType', 'Document', 'Qualification', 'QualificationDegree',
            'ContractType', 'PaymentType', 'History', 'HistoryMove', 'HistoryGroup', 
            'Salary', 'SalaryLine', 'HourType']
__metaclass__ = PoolMeta

company_domain=[If (Eval('context', {}).get('company', False),
                    ('parent', 'child_of', [Eval('context', {}).get('company', None)]),
                    ('id', '!=', None) )
                ]

class Employee(ModelSQL, ModelView):
    'Employee'
    __name__ = 'company.employee'
    company = fields.Many2One('company.company', 'Company', required=True, select=True, 
        domain=company_domain, on_change=['company'])
    first_name = fields.Char('First name', required=True)
    middle_name = fields.Char('Middle name')
    last_name = fields.Char('Last name', required=True)
    photo = fields.Binary('Photo')
    position = fields.Many2One('rrhh.position', 'Position', required=True, 
        domain=[
            If(Bool(Eval('company_id')),
                ('department.company', '=', Eval('company_id')),
                ('department', '=', None))],
        depends=['company_id'])
    department = fields.Function(fields.Char('Department'), 'get_department')
    contract_type = fields.Many2One('rrhh.contract.type', 'Contract type', required=True, 
        domain=[
            If(Bool(Eval('company_id')),
                ('company', '=', Eval('company_id')),
                ('company', '=', None))],
        depends=['company_id'])
    payment_type = fields.Many2One('rrhh.payment.type', 'Payment type', required=True) 
    date_start = fields.Date('Start date')
    date_finish = fields.Date('Finish date')
    salary = fields.Many2One('rrhh.salary', 'Salary', required=True, 
        domain=[
            If(Bool(Eval('company_id')),
                ('company', '=', Eval('company_id')),
                ('company', '=', None))],
        depends=['company_id'])
    history = fields.One2Many('rrhh.history', 'employee', 'History')
    instruction_level = fields.Many2One('rrhh.instruction.level', 'Instruction level', required=True)
    documents = fields.One2Many('rrhh.document', 'employee', 'Documents')
    qualifications = fields.One2Many('rrhh.qualification', 'employee', 'Qualification')
    supervisor = fields.Many2One('company.employee', 'Supervisor') 
    subordinates = fields.One2Many('company.employee', 'supervisor', 'Subordinates', readonly=True)
    marital_status = fields.Selection([
        ('single', 'Single'),
        ('married', 'Married'),
        ('divorced', 'Divorced'),
        ('widowed', 'Widowed'),
        ('other', 'Other'),
    ], 'Marital status', required=True)
    genre = fields.Selection([
        ('male', 'Male'),
        ('female', 'Female'),
    ], 'Genre', required=True)
    birth_date = fields.Date('Birth date', required=True)
    birth_country = fields.Many2One('country.country', 'Country of birth', required=True)
    nationality = fields.Many2One('country.country', 'Nationality', required=True)
    residence = fields.Many2One('country.country', 'Country of residence', required=True)
    age = fields.Function(fields.Char('Age'), 'get_age')
    dependents = fields.One2Many('rrhh.dependent', 'employee', 'Dependents')
    company_id = fields.Function(fields.Many2One('company.company', 'Company',
            on_change_with=['company']), 'on_change_with_company_id')

    @staticmethod
    def default_company():
        return Transaction().context.get('company')

    @staticmethod
    def compute_age(party_dob):
        if not party_dob:
            return 'No Birth date!'

        now = datetime.now()
        dob = datetime.strptime(str(party_dob), '%Y-%m-%d')
        delta = relativedelta(now, dob)

        years_months_days = str(delta.years) + 'y ' \
                + str(delta.months) + 'm ' \
                + str(delta.days) + 'd'

        return years_months_days

    def get_age(self, name):
        return self.compute_age(self.birth_date)

    def get_department(self, name):
        if self.position:
            return self.position.department.name

    def on_change_company(self):
        res = {}
        res['position'] = None
        return res
        
    def on_change_with_company_id(self, name=None):
        if self.company:
            return self.company.id


class Dependent(ModelSQL, ModelView):
    'Employee dependents'
    __name__ = 'rrhh.dependent'
    name = fields.Char('Name', required=True)
    employee = fields.Many2One('company.employee', 'Employee', required=True)
    relation = fields.Many2One('rrhh.dependent.relation', 'Relation', required=True)
    birth_date = fields.Date('Birth date', required=True)
    age = fields.Function(fields.Char('Age'), 'get_age')
    notes = fields.Text('Notes')

    def get_age(self, name):
        employee = Pool().get('company.employee')
        return employee.compute_age(self.birth_date)


class DependentRelation(ModelSQL, ModelView):
    'Dependent relation'
    __name__ = 'rrhh.dependent.relation'
    name = fields.Char('Name', required=True, translate=True)
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True


class Department(ModelSQL, ModelView):
    'Company Department'
    __name__ = 'rrhh.department'
    name = fields.Char('Name', required=True, translate=True)
    company = fields.Many2One('company.company', 'Company', select=True, required=True,
        domain=company_domain, 
        on_change=['company'])
    parent = fields.Many2One('rrhh.department', 'Parent',
        domain=[
            If(Bool(Eval('company_id')),
                ('company', '=', Eval('company_id')),
                ('company', '=', None))],
        depends=['company_id'])
    company_id = fields.Function(fields.Many2One('company.company', 'Company',
            on_change_with=['company']), 'on_change_with_company_id')
    childs = fields.One2Many('rrhh.department', 'parent', 'Children', readonly=True)
    positions = fields.One2Many('rrhh.position', 'department', 'Positions', readonly=True)
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True

    @staticmethod
    def default_company():
        return Transaction().context.get('company')

    def on_change_company(self):
        res = {}
        res['parent'] = None
        return res        
        
    def on_change_with_company_id(self, name=None):
        if self.company:
            return self.company.id


class Position(ModelSQL, ModelView):
    'Company Position'
    __name__ = 'rrhh.position'
    name = fields.Char('Name', required=True, translate=True)
    department = fields.Many2One('rrhh.department', 'Department', select=True, required=True)
    company = fields.Function(fields.Char('Company'), 'get_company')
    parent = fields.Many2One('rrhh.position', 'Parent',
        domain=[
            If(Bool(Eval('department_id')),
                ('department', '=', Eval('department_id')),
                ('department', '=', None)),
            ], depends=['department_id'])
    department_id = fields.Function(fields.Many2One('rrhh.department', 'Department',
            on_change_with=['department']), 'on_change_with_department_id')
    childs = fields.One2Many('rrhh.position', 'parent', 'Children')
    description = fields.Text('Description')
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True

    def on_change_department(self):
        res = {}
        res['parent'] = None
        return res
        
    def on_change_with_department_id(self, name=None):
        if self.department:
            return self.department.id

    def get_company(self, name):
        if self.department:
            return self.department.company.rec_name


class InstructionLevel(ModelSQL, ModelView):
    'Instruction level'
    __name__ = 'rrhh.instruction.level'
    name = fields.Char('Name', required=True, translate=True)
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True


class DocumentType(ModelSQL, ModelView):
    'Document type'
    __name__ = 'rrhh.document.type'
    name = fields.Char('Name', required=True, translate=True)
    notes = fields.Text('Notes')


class Document(ModelSQL, ModelView):
    'Employee document'
    __name__ = 'rrhh.document'
    _rec_name = 'type'
    employee = fields.Many2One('company.employee', 'Employee', required=True)
    type = fields.Many2One('rrhh.document.type', 'Type', required=True)
    copy = fields.Binary('Copy')
    country = fields.Many2One('country.country', 'Country', required=True)
    description = fields.Char('Number', help="Document description or number")
    date_issue = fields.Date('Issue date')
    date_expiration = fields.Date('Expiration date')
    mandatory = fields.Boolean('Mandatory')
    notes = fields.Text('Notes')

    @classmethod
    def __setup__(cls):
        super(Document, cls).__setup__()
        cls._sql_constraints = [
            ('doc_uniq', 'unique(employee, type, country)', 
                'Employee document must be uniq per type and country!'),
        ]

    @staticmethod
    def default_mandatory():
        return False

    def get_rec_name(self, name):
        return self.type.rec_name


class Qualification(ModelSQL, ModelView):
    'Qualification'
    __name__ = 'rrhh.qualification'
    employee = fields.Many2One('company.employee', 'Employee', required=True)
    name = fields.Char('Name', required=True, translate=True)
    type = fields.Selection([
        ('education', 'Education'),
        ('certification', 'Certification'),
        ('work', 'Work experience'),
        ('skill', 'Skill'),
        ('language', 'Language'),
    ], 'Type', required=True, translate=True, help='Qualification type')
    degree = fields.Many2One('rrhh.qualification.degree', 'Degree', 
        help='The qualification degree, if applicable. It could be "None", "Unfinished" or any valid degree.')
    notes = fields.Text('Notes')

    @classmethod
    def __setup__(cls):
        super(Qualification, cls).__setup__()
        cls._order.insert(0, ('type', 'DESC'))


class QualificationDegree(ModelSQL, ModelView):
    'Qualification degree'
    __name__ = 'rrhh.qualification.degree'
    name = fields.Char('Name', required=True, translate=True) 
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True

class ContractType(ModelSQL, ModelView):
    'Contract type'
    __name__ = 'rrhh.contract.type'
    name = fields.Char('Name', required=True, translate=True)
    company = fields.Many2One('company.company', 'Company', select=True, required=True,
        domain=company_domain)
    conditions = fields.Text('Conditions')

    @staticmethod
    def default_company():
        return Transaction().context.get('company')


class PaymentType(ModelSQL, ModelView):
    'Contract Payment type'
    __name__ = 'rrhh.payment.type'
    name = fields.Char('Name', required=True, translate=True)
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True


class History(ModelSQL, ModelView):
    'History. It register events related to an employee'
    __name__ = 'rrhh.history'
    date = fields.Date('Date')
    employee = fields.Many2One('company.employee', 'Employee', required=True)
    history_move = fields.Many2One('rrhh.history.move', 'Move', required=True)
    notes = fields.Text('Notes')

    @classmethod
    def __setup__(cls):
        super(History, cls).__setup__()
        cls._order.insert(0, ('date', 'DESC'))


class HistoryMove(ModelSQL, ModelView):
    'History move'
    __name__ = 'rrhh.history.move'
    name = fields.Char('Name', required=True, translate=True) 
    history_group = fields.Many2One('rrhh.history.group', 'Group', required=True)
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True

  
class HistoryGroup(ModelSQL, ModelView):
    'History group'
    __name__ = 'rrhh.history.group'
    name = fields.Char('Name', required=True, translate=True) 
    parent = fields.Many2One('rrhh.history.group', 'Parent')
    childs = fields.One2Many('rrhh.history.group', 'parent', 'Children')
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True


class Salary(ModelSQL, ModelView):
    'Salary'
    __name__ = 'rrhh.salary'
    name = fields.Char('Name', required=True, translate=True)
    currency = fields.Many2One('currency.currency', 'Currency', required=True)
    lines = fields.One2Many('rrhh.salary.line', 'salary', 'Lines')
    company = fields.Many2One('company.company', 'Company', select=True, required=True,
        domain=company_domain)

    @staticmethod
    def default_company():
        return Transaction().context.get('company')


class SalaryLine(ModelSQL, ModelView):
    'Salary line'
    __name__ = 'rrhh.salary.line'
    salary = fields.Many2One('rrhh.salary', 'Salary',
            ondelete='CASCADE', select=True, required=True)
    hour_type = fields.Many2One('rrhh.hour.type', 'Hour type', required=True)
    amount = fields.Numeric('Value', digits=(16, 6), required=True)


class HourType(ModelSQL, ModelView):
    'Salary hour type'
    __name__ = 'rrhh.hour.type'
    name = fields.Char('Name', required=True, translate=True)
    notes = fields.Text('Notes')
    active = fields.Boolean('Active')

    @staticmethod
    def default_active():
        return True

